package com.lhc.web.controller;

import com.lhc.web.dto.ESRequestParamDTO;
import org.apache.http.HttpHost;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestClientBuilder;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.RangeQueryBuilder;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.io.IOException;

/**
 * @Author lhc
 * @Date 2021/8/2 9:04
 */
@RestController
@RequestMapping("/es/product")
public class ProductController {

    //索引库名字
    private static final String product_db_name = "product_db";

    //客户端连接
    private RestHighLevelClient restHighLevelClient;

    public ProductController() {
        RestClientBuilder restClientBuilder = RestClient.builder(
                new HttpHost("localhost", 9200, "http"),
                new HttpHost("192.168.61.143", 9200, "http")
        );
        restHighLevelClient = new RestHighLevelClient(restClientBuilder);
    }


    /**
     * 查询商品
     *
     * @param requestParamDTO 请求对象
     * @throws IOException 异常
     */
    @PostMapping("/find")
    public void find(@RequestBody ESRequestParamDTO requestParamDTO) throws IOException {
        //1.封装检索对象
        SearchRequest searchRequest = buildSearchRequest(requestParamDTO);
        //2.发送请求
        SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
        //3.封装结果集
        System.out.println(searchResponse);
    }

    /**
     * 构建es检索对象
     *
     * @return 前端请求参数
     */
    private SearchRequest buildSearchRequest(ESRequestParamDTO requestParamDTO) {
        //封装查询的DSL相关信息  1.query、2.排序、3.分页、4.高亮
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();

        //一。query 关键字 品牌id 分类id 价格 是否有库存
        BoolQueryBuilder boolQueryBuilder = this.buildBoolQueryBuilder(requestParamDTO);
        searchSourceBuilder.query(boolQueryBuilder);


//        //二。排序 price_desc
//        if (!StringUtils.isEmpty(requestParamDTO.getSort())) {
//            String[] sorts = requestParamDTO.getSort().split("_");
//            SortOrder sortOrder = "asc".equalsIgnoreCase(sorts[1]) ? SortOrder.ASC : SortOrder.DESC;
//            searchSourceBuilder.sort(sorts[0], sortOrder);
//        }
//
//
//        //三。分页
//        searchSourceBuilder.from((requestParamDTO.getPageNum() - 1) * 10);
//        searchSourceBuilder.size(10);
//
//        //四。高亮
//        if (!StringUtils.isEmpty(requestParamDTO.getKeyword())) {
//            HighlightBuilder highlightBuilder = new HighlightBuilder();
//            highlightBuilder.field("name");
//            highlightBuilder.preTags("<b style='color:red'>");
//            highlightBuilder.postTags("</b>");
//            searchSourceBuilder.highlighter(highlightBuilder);
//        }
//
//        //五。聚合
//        //根据品牌聚合
//        TermsAggregationBuilder brandAgg = AggregationBuilders.terms("brand_agg");
//        brandAgg.field("brandId").size(10);
//        //品牌下再根据品牌名、品牌图片再次聚合
//        brandAgg.subAggregation(AggregationBuilders.terms("brand_name_agg")).field("brand_name").size(1);
//        brandAgg.subAggregation(AggregationBuilders.terms("brand_img_agg")).field("brandImg").size(1);
//        searchSourceBuilder.aggregation(brandAgg);
//
//        //根据属性信息进行聚合
//        NestedAggregationBuilder attrAgg = AggregationBuilders.nested("attr_agg", "attrs");
//        //根据属性id进行聚合
//        TermsAggregationBuilder attr_id_agg = AggregationBuilders.terms("arrt_id_agg").field("attrs.attrId");
//        attrAgg.subAggregation(attr_id_agg);
//        //属性id下再根据属性名称、属性值进行聚合
//        TermsAggregationBuilder attr_name_agg = AggregationBuilders.terms("attr_name_agg").field("attrs.attrName").size(1);
//        attr_id_agg.subAggregation(attr_name_agg);
//        TermsAggregationBuilder attr_value_agg = AggregationBuilders.terms("attr_value_agg").field("attrs.attrValue").size(50);
//        attr_id_agg.subAggregation(attr_value_agg);
//        searchSourceBuilder.aggregation(attrAgg);

        System.out.println("构建的DSL语句 {}:" + searchSourceBuilder.toString());
        return new SearchRequest(new String[]{product_db_name}, searchSourceBuilder);
    }

    /**
     * 构建BoolQueryBuilder
     *
     * @param requestParamDTO 请求对象
     * @return BoolQueryBuilder
     */
    private BoolQueryBuilder buildBoolQueryBuilder(ESRequestParamDTO requestParamDTO) {
        //一。query 关键字 品牌id 分类id 价格 是否有库存
        BoolQueryBuilder boolQueryBuilder = new BoolQueryBuilder();
        //1.根据关键字keyword进行查询 query-bool-must
        if (!StringUtils.isEmpty(requestParamDTO.getKeyword())) {
            //单字段查询
            boolQueryBuilder.must(QueryBuilders.matchQuery("name", requestParamDTO.getKeyword()));
            //多字段查询
            //boolQueryBuilder.must(QueryBuilders.multiMatchQuery(requestParamDTO.getKeyword(), "name", "keywords", "subTitle"));
        }
        //2.根据品牌id、类目id等进行过滤 query-bool-filter
        if (!StringUtils.isEmpty(requestParamDTO.getBrandId())) {
            boolQueryBuilder.filter(QueryBuilders.termQuery("brandId", requestParamDTO.getBrandId()));
        }
        if (!StringUtils.isEmpty(requestParamDTO.getCategoryId())) {
            boolQueryBuilder.filter(QueryBuilders.termQuery("categoryId", requestParamDTO.getCategoryId()));
        }
        //3.判断是否有库存
        if (null != requestParamDTO.getHasStock()) {
            boolQueryBuilder.filter(QueryBuilders.termQuery("hasStock", requestParamDTO.getHasStock()));
        }
        //4.价格信息
        if (!StringUtils.isEmpty(requestParamDTO.getPrice())) {
            RangeQueryBuilder rangeQueryBuilder = QueryBuilders.rangeQuery("price");
            String[] prices = requestParamDTO.getPrice().split("_");
            if (prices.length == 2) {
                rangeQueryBuilder.gte(prices[0]).lte(prices[1]);
            } else if (prices.length == 1) {
                if (requestParamDTO.getPrice().startsWith("_")) {
                    rangeQueryBuilder.lte(prices[0]);
                }
                if (requestParamDTO.getPrice().endsWith("_")) {
                    rangeQueryBuilder.gte(prices[0]);
                }
            }
            boolQueryBuilder.filter(rangeQueryBuilder);
        }
        //5.nested
//        BoolQueryBuilder nestedBoolQueryBuilder = new BoolQueryBuilder();
//        NestedQueryBuilder nestedQueryBuilder = QueryBuilders.nestedQuery("attrs", nestedBoolQueryBuilder, ScoreMode.Avg);
//        boolQueryBuilder.filter(nestedQueryBuilder);

        return boolQueryBuilder;
    }
}